﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Caching;

namespace Project.Tool
{
	public class CacheHelper
    {
		/// <summary>
		/// 插入
		/// </summary>
		public class Set
		{

			/// <summary>
			/// 有效期顺延 [相对时间 - relative time]
			/// </summary>
			public void RT(string key, object value, int seconds = 10 * 60)
			{
				RT_Tool(key, value, seconds);
			}

			/// <summary>
			/// 有效期固定 [固定时间 - fixed time]
			/// </summary>
			public void FT(string key, object value, int seconds = 10 * 60)
			{
				FT_Tool(key, value, seconds);
			}

			/// <summary>
			/// 缓存依赖
			/// </summary>
			public void RO(string key, object value, string path, int seconds = 0, bool type = true)
			{
				RO_Tool(key, value, path, seconds, type);
			}

			/// <summary>
			/// 清除回调
			/// </summary>
			public void CB(string key, object value, int seconds = 60 * 60 * 24)
			{
				CB_Tool(key, value, seconds);
			}


			/// <summary>
			/// 构造
			/// </summary>
			/// <param name="key">关键字</param>
			/// <param name="value">缓存数据</param>
			/// <param name="seconds">缓存时间 [6分钟]</param>
			private void FT_Tool(string key, object value, int seconds)
			{
				Cache cache = HttpRuntime.Cache;

				cache.Insert(
					key,
					value,
					null,
					DateTime.Now.AddSeconds(seconds),
					Cache.NoSlidingExpiration);
			}

			/// <summary>
			/// 构造
			/// </summary>
			/// <param name="key">关键字</param>
			/// <param name="value">缓存数据</param>
			/// <param name="seconds">缓存时间 [6分钟]</param>
			private void RT_Tool(string key, object value, int seconds)
			{
				Cache cache = HttpRuntime.Cache;

				cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(seconds));
			}

			/// <summary>
			/// 构造
			/// </summary>
			/// <param name="key">关键字</param>
			/// <param name="value">缓存数据</param>
			/// <param name="path">依赖文件路径</param>
			/// <param name="seconds">有效时间</param>
			/// <param name="type">默认顺延方式 [true - falst]</param>
			private void RO_Tool(string key, object value, string path, int seconds, bool type)
			{
				Cache cache = HttpRuntime.Cache;

				if ( seconds.Is(0) )

					cache.Insert(key, value, new CacheDependency(path.ServerPath()));

				else {

					if ( type ) cache.Insert(key, value, new CacheDependency(path.ServerPath()), Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(seconds));

					else cache.Insert(key, value, new CacheDependency(path.ServerPath()), DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration);

				}


			}

			/// <summary>
			/// 构造
			/// </summary>
			/// <param name="key">关键字</param>
			/// <param name="value">缓存数据</param>
			/// <param name="seconds">有效时间</param>
			private void CB_Tool(string key, object value, int seconds)
			{
				Cache cache = HttpRuntime.Cache;

				cache.Add(key, value, null, DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration, CacheItemPriority.Default, CallBack);
			}

			/// <summary>
			/// 回调操作
			/// </summary>
			/// <param name="key"></param>
			/// <param name="value"></param>
			/// <param name="reason"></param>
			private void CallBack(string key, object value, CacheItemRemovedReason reason)
			{
				//Action collBack
			}

			class Config
			{

			}
		}

		/// <summary>
		/// 修改数据
		/// </summary>
		/// <param name="Key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static bool Update(string Key, string value)
		{
			try {

				HttpRuntime.Cache[Key] = value;

				return true;

			} catch {
				return false;
			}
		}

		/// <summary>
		/// 获取缓存数据
		/// </summary>
		/// <param name="Key">缓存Key</param>
		/// <returns></returns>
		public static T Get<T>(string Key)
		{
			try{
				return (T) HttpRuntime.Cache[Key];
			}
			catch {
				return default(T);
			}
		}

		/// <summary>
		/// 获取缓存数据
		/// </summary>
		/// <param name="Key">关键字</param>
		/// <param name="Func">方法</param>
		/// <param name="type">类型 [true - 顺延 : falst - 固定]</param>
		/// <param name="second">时间 - [秒 default(60)]</param>
		/// <returns></returns>
		public static T Get<T>(string Key, Func<T> Func,bool type = true,int second = 600)
		{
			object value = HttpRuntime.Cache[Key];

			if ( value.Is(null) ) {

				Set ins = new Set();

				if( type )
					ins.RT(Key, Func(), second);
				else
					ins.FT(Key, Func(), second);

				return (T) HttpRuntime.Cache[Key];

			}
			else
				return (T) value;
		}
	}
}
